home *** CD-ROM | disk | FTP | other *** search
- /* 02.04.1989 amn (latest edit) */
-
- /* PDEF0.c - printer driver for Macintosh and HP DeskJet, draft printing. */
-
- /* Compiles into 'PDEF' resource, id 0, name ''. */
- /* We cannot use any global variables in this code. However, the globals of the */
- /* low-level driver (XPrint) are available thru the handle 'dCtlStorage' in the */
- /* driver's device control entry. */
-
- /* This resource is placed into the printer resource file */
- /* 'HP DeskJet', type 'PRER', creator 's89^' as */
- /* 'PDEF' 0 '' by 'PRER_Builder' utility program. This utility adds a small jump */
- /* table in front of the code produced by LightspeedC. */
-
- /* These procedures handle draft printing, ie. direct commands to printer. */
- /* HP DeskJet is quite capable of accepting direct print head positioning: */
- /* it tries to accumulate print data in its 16 kB buffer and sort it out */
- /* to print it in optimal order. Thus we don't try to avoid reverse line feeds. */
-
- /* Authors: Ari Mujunen (amn@hutcs.hut.fi) and Olli Arnberg (oar@hutcs.hut.fi). */
- /* Copyright Ari Mujunen, Olli Arnberg 1989. */
- /* You may redistribute the driver (=printer resource file, source files, */
- /* documentation file(s), and the file 'Copyright and Source Offer') */
- /* only _non-commercially_ and _in its entirety_. */
- /* See the file 'Copyright and Source Offer' and/or documentation for details. */
- /* Acknowledgements: Special thanks to Mr. Earle R. Horton for his 'Daisy' */
- /* daisywheel printer driver and its source code published in 'MacTutor', Nov-Dec 1987. */
- /* This driver served as a basis and inspiration for our work. It also */
- /* proofed that a Macintosh printer driver can be done despite the lack of */
- /* documentation from Apple. */
-
- /* Change history: */
- /* Version When Who Why */
- /* 2.0 21.11.1988 amn Original rewrite. */
- /* 23.11.1988 amn Simplistic draft (direct positioning commands to printer). */
- /* 24.11.1988 amn Read printed listing... */
- /* 25.11.1988 amn Implementing justified text, ie. SpaceExtra. */
- /* 27.11.1988 amn Implementing justified text, ie. SpaceExtra. */
- /* 09.12.1988 amn User-specifiable setting 'movePrintPositionBeforeEachWord'. */
- /* 12.12.1988 amn HP DeskJet physical margins taken into account. */
- /* 07.03.1989 amn Character conversion table from Mac to HP Roman8. */
- /* 10.03.1989 amn Call stdText with Ptr, not QDPtr to text buffer. */
- /* 25.03.1989 amn,oar The global file refNums are not used any longer because of MF. */
- /* 28.03.1989 amn Settable printer origin. */
- /* 2.1 02.04.1989 amn,oar Released version. */
-
-
- #include "common_mac_includes.h"
-
- /* Mac OS includes specific to this module: */
- #include <pascal.h>
-
-
- #include "prglobals.h"
-
- #include "procedures_for_PDEF1.c"
- #include "procedures_for_PDEF5.c"
-
-
-
- /* Function prototypes. */
-
- /* Procedure dispatcher. */
- void main(int);
-
- /* Initializes a specialized grafPort for printing. */
- pascal TPPrPort myPrOpenDoc(THPrint, TPPrPort, Ptr);
-
- /* Disposes the printing grafPort. */
- pascal void myPrCloseDoc(TPPrPort);
-
- /* Reinitializes the printing grafPort. */
- pascal void myPrOpenPage(TPPrPort, TPRect);
-
- /* Feeds next sheet. :-) */
- pascal void myPrClosePage(TPPrPort);
-
-
- /* Replaces the standard QuickDraw low-level procedure for drawing text. */
- pascal void myStdText(int, Ptr, Point, Point);
- void printOneWord(int, Ptr, Point, Point);
-
- /* Used to call standard QD text-drawing procedure. We use prototypes... */
- pascal void CallPascal(int, Ptr, Point, Point, Ptr);
-
-
-
- /* Function definitions. */
-
-
- void
- main(routineSelector)
- int routineSelector;
- {
- /* The jump table code inserted before our code resource by 'PRER_Builder' */
- /* utility program pushes a word onto stack indicating which routine is called. */
- /* We pop it off the stack and select an appropriate routine. */
-
- switch(routineSelector) {
- case 0:
- asm {
- unlk a6 ;; LSC generates an 'link' instruction to access parameters
- move.l (a7)+, d0 ;; pop return address to our jump table code (discarded)
- move.w (a7)+, d0 ;; pop argument 'routineSelector'
- jmp myPrOpenDoc
- }
- case 1:
- asm {
- unlk a6
- move.l (a7)+, d0
- move.w (a7)+, d0
- jmp myPrCloseDoc
- }
- case 2:
- asm {
- unlk a6
- move.l (a7)+, d0
- move.w (a7)+, d0
- jmp myPrOpenPage
- }
- case 3:
- asm {
- unlk a6
- move.l (a7)+, d0
- move.w (a7)+, d0
- jmp myPrClosePage
- }
- } /* switch */
-
- /* We should not arrive here; Printing Manager has called a non-existent routine. */
- SysError(5); /* check bounds trap ??? */
- } /* main */
-
-
- /*
- This function is supposed to return a pointer to a specialized GrafPort (a TPrPort) customized
- for printing. Due to the paucity of documentation on how to go about this, I do not know whether
- I am going about this in exactly the right way, but I sure hope so. I set portBits.bounds for
- the port to the empty Rect (0,0,0,0) and then install the standard QuickDraw routines as
- GrafProcs. In place of StdText, I put my own StdText routine. Hopefully, QuickDraw will keep
- track of the correct pen location for me, and call my routine whenever it is necessary to draw
- text.
- Other tasks: save a copy of the user print record in the printer resource file
- to remember user's last choices in job dialog (resolution etc.).
- */
-
-
- #define DEBUG_OPEN_PRINT_RECORD
-
- pascal TPPrPort
- myPrOpenDoc(hPrint, pPrPort, pIOBuf)
- THPrint hPrint;
- TPPrPort pPrPort;
- Ptr pIOBuf;
- {
- TPPrPort thisPort;
- ptXprintGlobals xPrintGlobals;
- ptPrParam pXPrintParameterBlock;
- OSErr retCode;
-
- { /* Lock this code resource in memory (Printing Manager should do this, but...). */
- Handle us;
-
- us = (Handle)GetResource('PDEF', 0);
- if (us == nil) {
- PrintErr = ResError();
- return(nil);
- }
- HLock(us);
- }
-
- if (pPrPort == nil) { /* printing GrafPort NOT preallocated */
- if ((thisPort = (TPPrPort)NewPtr((long)sizeof(TPrPort))) == nil) {
- PrintErr = iMemFullErr;
- return(nil);
- }
- thisPort->fOurPtr = TRUE;
- }
- else { /* printing GrafPort already preallocated */
- thisPort = pPrPort;
- thisPort->fOurPtr = FALSE;
- }
-
- xPrintGlobals = GET_XPRINT_GLOBALS;
- pXPrintParameterBlock = &xPrintGlobals->xPrintParameterBlock;
-
-
- /* Initialize GrafPort */
- OpenPort(&thisPort->gPort);
- setRectsAndRgns(thisPort, hPrint);
-
- /* Fill out QuickDraw low-level drawing procedures (gProcs) for this port. */
- SetStdProcs(&thisPort->gProcs);
- thisPort->gProcs.textProc = (QDPtr)myStdText;
- thisPort->gPort.grafProcs = &thisPort->gProcs;
-
- /* Initialize the printer using standard printer control call. */
- pXPrintParameterBlock->csCode = iPrDevCtl;
- pXPrintParameterBlock->lParam1 = lPrReset;
- if ((retCode = PBControl(pXPrintParameterBlock, FALSE)) != noErr)
- goto cleanUp;
-
- #define NUMBER_OF_THIS_PDEF 0
- #include "save_last_used.c"
-
- /* Page range etc. are available in global print record. */
- xPrintGlobals->printRecord = **hPrint;
-
- /* If application has not requested an own idle procedure, we set our default one. */
- if (xPrintGlobals->printRecord.prJob.pIdleProc == nil)
- xPrintGlobals->printRecord.prJob.pIdleProc = (ProcPtr)checkForCommandPeriod;
-
- /* High-level printing code always counts pages from 1 (IM II-156). */
- xPrintGlobals->pageCounter = 1;
-
- retCode = noErr;
- cleanUp:
- PrintErr = retCode;
- if (retCode == noErr)
- return(thisPort);
- else {
- if (thisPort->fOurPtr)
- DisposPtr(thisPort);
- return(nil);
- }
- } /* myOpenDoc */
-
-
- pascal void
- myPrCloseDoc(pPrPort)
- TPPrPort pPrPort;
- {
- if (pPrPort == nil)
- return;
-
- ClosePort(pPrPort);
- if (pPrPort->fOurPtr)
- DisposPtr(pPrPort);
- } /* myPrCloseDoc */
-
-
- pascal void
- myPrOpenPage(pPrPort, pPageFrame)
- TPPrPort pPrPort;
- TPRect pPageFrame;
- {
- ptXprintGlobals xPrintGlobals;
- TPPrint pPrint;
-
- if (pPrPort == nil)
- return;
-
- /* Don't touch 'pPageFrame' in draft mode (IM II-159). */
-
- xPrintGlobals = GET_XPRINT_GLOBALS;
-
- /* Port should be returned to initial state (as initialized in OpenDoc). ??? */
- InitPort(pPrPort);
- pPrint = &xPrintGlobals->printRecord;
- setRectsAndRgns(pPrPort, &pPrint);
-
- /* Fill out QuickDraw low-level drawing procedures (gProcs) for this port. */
- SetStdProcs(&pPrPort->gProcs);
- pPrPort->gProcs.textProc = (QDPtr)myStdText;
- pPrPort->gPort.grafProcs = &pPrPort->gProcs;
-
- /* if (PrintErr != noErr) then some kind of error has occurred during previous page. */
- /* Applications shouldn't call us then, but... */
-
- if ((xPrintGlobals->pageCounter >= xPrintGlobals->printRecord.prJob.iFstPage)
- && (xPrintGlobals->pageCounter <= xPrintGlobals->printRecord.prJob.iLstPage)
- && (PrintErr == noErr)
- && (xPrintGlobals->printRecord.prStl.feed == feedCut))
- if (waitNextPage() == FALSE) /* Dialog 'Insert next sheet...' */
- PrintErr = iPrAbort;
- } /* myPrOpenPage */
-
-
- pascal void
- myPrClosePage(pPrPort)
- TPPrPort pPrPort;
- {
- ptXprintGlobals xPrintGlobals;
- ptPrParam pXPrintParameterBlock;
- OSErr retCode;
-
- if (pPrPort == nil)
- return;
-
- /* if (PrintErr != noErr) then some kind of error has occurred during page. */
- /* Applications will call us nevertheless. */
-
- xPrintGlobals = GET_XPRINT_GLOBALS;
- pXPrintParameterBlock = &xPrintGlobals->xPrintParameterBlock;
-
- if ((xPrintGlobals->pageCounter >= xPrintGlobals->printRecord.prJob.iFstPage)
- && (xPrintGlobals->pageCounter <= xPrintGlobals->printRecord.prJob.iLstPage)) {
- /* Form feed using standard printer control call. */
- pXPrintParameterBlock->csCode = iPrDevCtl;
- pXPrintParameterBlock->lParam1 = lPrPageEnd;
- if ((retCode = PBControl(pXPrintParameterBlock, FALSE)) != noErr)
- PrintErr = retCode;
- }
-
- xPrintGlobals->pageCounter++;
- } /* myClosePage */
-
-
- /*** #define DEBUG_TEXT_DRAWING ***/
-
- pascal void
- myStdText(byteCount, textBuffer, numer, denom)
- int byteCount;
- Ptr textBuffer;
- Point numer, denom;
- {
- ptXprintGlobals xPrintGlobals;
- GrafPtr savePort;
-
- xPrintGlobals = GET_XPRINT_GLOBALS;
-
- GetPort(&savePort);
- (*(xPrintGlobals->printRecord.prJob.pIdleProc))();
- SetPort(savePort);
-
- if ((xPrintGlobals->pageCounter >= xPrintGlobals->printRecord.prJob.iFstPage)
- && (xPrintGlobals->pageCounter <= xPrintGlobals->printRecord.prJob.iLstPage)
- && (PrintErr == noErr))
- {
- int i, startOfWord;
- GrafPtr gp;
-
- #define CHARACTERS 0
- #define BLANKS 1
-
- startOfWord = 0;
- GetPort(&gp);
- if ((!(xPrintGlobals->currentSettings.movePrintPositionBeforeEachWord))
- && (gp->spExtra == 0L))
- /* we assume that accurate positioning of word beginnings is not required */
- i = byteCount + 1;
- else {
- int state;
-
- i = 0;
- state = CHARACTERS;
- while(i<=byteCount) {
- switch(state) {
- case CHARACTERS:
- if (textBuffer[i] == ' ')
- state = BLANKS;
- else
- i++;
- break;
- case BLANKS:
- if (textBuffer[i] == ' ')
- i++;
- else {
- printOneWord(i-startOfWord, &textBuffer[startOfWord], numer, denom);
- startOfWord = i;
- state = CHARACTERS;
- }
- break;
- } /* switch */
- } /* while */
- }
-
- /* Last (or only) word of this string. */
- printOneWord(i-startOfWord-1, &textBuffer[startOfWord], numer, denom);
-
- } /* if printing allowed */
- } /* myStdText */
-
-
- void
- printOneWord(byteCount, textBuffer, numer, denom)
- int byteCount;
- Ptr textBuffer;
- Point numer, denom;
- {
- ptXprintGlobals xPrintGlobals;
- ptPrParam pXPrintParameterBlock;
-
- Point thePoint;
- long theLong;
- Str255 theNumAsString;
- QDProcs stdProcs;
- StringHandle ct; /* character conversion table */
- int i;
- Str255 convertedDeskJetWord;
-
- xPrintGlobals = GET_XPRINT_GLOBALS;
- pXPrintParameterBlock = &xPrintGlobals->xPrintParameterBlock;
-
- GetPen(&thePoint);
- LocalToGlobal(&thePoint); /* Someone may have adjusted the origin. */
- #ifdef DEBUG_TEXT_DRAWING
- printString((StringPtr)"\pAt (");
- NumToString((long)thePoint.v, theNumAsString);
- printString(theNumAsString);
- printString((StringPtr)"\p,");
- NumToString((long)thePoint.h, theNumAsString);
- printString(theNumAsString);
- printString((StringPtr)"\p) scaled ((");
- NumToString((long)numer.v, theNumAsString);
- printString(theNumAsString);
- printString((StringPtr)"\p/");
- NumToString((long)denom.v, theNumAsString);
- printString(theNumAsString);
- printString((StringPtr)"\p),(");
- NumToString((long)numer.h, theNumAsString);
- printString(theNumAsString);
- printString((StringPtr)"\p/");
- NumToString((long)denom.h, theNumAsString);
- printString(theNumAsString);
- printString((StringPtr)"\p)) ");
- NumToString((long)byteCount, theNumAsString);
- printString(theNumAsString);
- printString((StringPtr)"\p characters:\r\n->");
- #else
- /* Position print head.*/
- printString((StringPtr)"\p\033&a");
- theLong = (long)thePoint.v * 720L / (long)xPrintGlobals->printRecord.prInfo.iVRes;
- NumToString(theLong, theNumAsString);
- printString(theNumAsString);
- printString((StringPtr)"\pV");
- printString((StringPtr)"\p\033&a");
- theLong = (long)thePoint.h * 720L / (long)xPrintGlobals->printRecord.prInfo.iHRes;
- NumToString(theLong, theNumAsString);
- printString(theNumAsString);
- printString((StringPtr)"\pH");
- #endif DEBUG_TEXT_DRAWING
-
- /* Convert characters from Mac code set to HP Roman8 using C89T-resource. */
- if ((ct = (StringHandle)GetResource('C89T', 0)) != nil) {
- LoadResource(ct);
- for(
- i=0;
- i < ((byteCount>sizeof(convertedDeskJetWord))
- ?(sizeof(convertedDeskJetWord))
- :byteCount);
- i++
- )
- convertedDeskJetWord[i] = (*ct)[((unsigned char *)textBuffer)[i]];
-
- pXPrintParameterBlock->lParam1 = (long)(&convertedDeskJetWord);
- pXPrintParameterBlock->lParam2 = (long)(i);
- }
- else {
- pXPrintParameterBlock->lParam1 = (long)textBuffer;
- pXPrintParameterBlock->lParam2 = (long)byteCount;
- }
-
- /* Send actual text. */
- pXPrintParameterBlock->csCode = iPrIOCtl;
- /* retCode = */ PBControl(pXPrintParameterBlock, FALSE);
- /* This must remain synchronous I/O, otherwise the local buffer may disappear. */
-
- #ifdef DEBUG_TEXT_DRAWING
- printString((StringPtr)"\p<-\r\n");
- #endif DEBUG_TEXT_DRAWING
-
- /* Move pen. */
- SetStdProcs(&stdProcs);
- CallPascal(byteCount, textBuffer, numer, denom, stdProcs.textProc);
- } /* printOneWord */
-